package com.zdp.chat.util;

import cn.hutool.extra.spring.SpringUtil;
import org.redisson.api.RList;
import org.redisson.api.RLock;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.client.protocol.ScoredEntry;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 缓存类，基于redisson
 */
public class CacheUtils {

    private static final RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);


    /**
     * 计分排序 默认8小时过期
     *
     * @param key   key
     * @param val   value
     * @param score 分值, 会话时间
     * @param <T>   value类型
     */
    public static <T> void zAdd(String key, T val, double score) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        sortedSet.add(score, val);
    }

    /**
     * 修改分数
     *
     * @param key   key
     * @param val   value
     * @param score 分值, 会话时间
     * @param <T>   value类型
     */
    public static <T> double zScore(String key, T val, double score) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        Double oldScore = sortedSet.getScore(val);
        if (Objects.isNull(oldScore)) {
            sortedSet.addScore(val, score);
            return score;
        }
        double addScore = score - oldScore;
        if (addScore > 0) {
            sortedSet.addScore(val, addScore);
        }
        return oldScore;
    }

    /**
     * 死寂排名
     *
     * @param key key
     * @param val value
     * @param <T> value类型
     */
    public static <T> void deathScore(String key, T val) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        sortedSet.add(0, val);
    }

    /**
     * 获取排名数据
     *
     * @param key   key
     * @param start 起始
     * @param end   结束
     * @param <T>   类型
     * @return 结果
     */
    public static <T> Collection<ScoredEntry<T>> zGet(String key, int start, int end) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.entryRangeReversed(start, end);
    }

    /**
     * 查询set数据
     *
     * @param key key
     * @param <T> 类型
     * @return 结果
     */
    public static <T> Collection<T> zGet(String key) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.readAll();
    }

    /**
     * 删除set数据
     *
     * @param key key
     * @param <T> 类型
     * @return 结果
     */
    public static <T> boolean zRem(String key, T val) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.remove(val);
    }

    /**
     * 获取排名score
     *
     * @param key key
     * @param val value
     * @param <T> 类型
     * @return 结果
     */
    public static <T> Double getScore(String key, T val) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.getScore(val);
    }

    public static <T> boolean zContain(String key, Collection<T> val) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.containsAll(val);
    }

    public static <T> boolean zContain(String key, Object val) {
        RScoredSortedSet<T> sortedSet = CLIENT.getScoredSortedSet(key);
        return sortedSet.contains(val);
    }

    /**
     * 获取redis 锁
     *
     * @param name key名称
     * @return 锁对象
     */
    public static RLock getLock(String name) {
        return CLIENT.getLock(name);
    }

    /**
     * 添加元素（list）
     *
     * @param key k
     * @param val v
     * @param <T> 类型
     */
    public static <T> void lPush(String key, T val) {
        RList<T> list = CLIENT.getList(key);
        list.addAsync(val);
    }

    /**
     * 取元素列表（list）
     *
     * @param key k
     * @param <T> 类型
     */
    public static <T> List<T> lGet(String key) {
        RList<T> list = CLIENT.getList(key);
        return list.readAll();
    }
}
